package com.tiancheng.trade.authserver.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.authserver.entity.AuthRole;
import com.tiancheng.trade.authserver.entity.AuthUserMapRole;
import com.tiancheng.trade.authserver.mapper.AuthUserMapRoleMapper;
import com.tiancheng.trade.authserver.service.IAuthRoleService;
import com.tiancheng.trade.authserver.service.IAuthUserMapRoleService;
import com.tiancheng.trade.commom.core.exception.AuthorizationException;
import com.tiancheng.trade.commom.core.exception.error.AuthErrorInfoEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: likailun
 * @Description:
 * @Date: create in 2024/10/22 11:04
 */
@Service
public class AuthUserMapRoleServiceImpl extends ServiceImpl<AuthUserMapRoleMapper, AuthUserMapRole> implements IAuthUserMapRoleService {

    @Resource
    private IAuthRoleService roleService;

    @Transactional
    @Override
    public int saveUserRole(Long userId, Set<Long> roleIds) {
        if (roleIds == null) {
            roleIds = new HashSet<>();
        }
        List<AuthUserMapRole> oldUMRs = this.getByUserId(userId);
        if (oldUMRs == null) {
            oldUMRs = new LinkedList<>();
        }
        Set<Long> oldRoleIds = oldUMRs.stream().map(AuthUserMapRole::getRoleId).collect(Collectors.toSet());
        Map<Long, AuthRole> oldRoles = new HashMap<>();
        if(CollectionUtils.isNotEmpty(oldRoleIds)){
            oldRoles=this.roleService.getByIds(oldRoleIds);
        }
        Map<Long, AuthRole> newRoles = new HashMap<>();
        if(CollectionUtils.isNotEmpty(roleIds)){
            newRoles=this.roleService.getByIds(roleIds);
        }
        Set<Long> saveRoleIds = new HashSet<>();
        int updateNum = 0;
        for (AuthRole role : newRoles.values()) {
            //原先已存在该角色
            if (oldRoleIds.contains(role.getId())) {
                saveRoleIds.add(role.getId());
            } else {
                //如果访问人有该角色的数据权限
                if (StpUtil.hasPermission(role.getDataPermissionCode())) {
                    saveRoleIds.add(role.getId());
                    updateNum++;
                } else {
                    throw new AuthorizationException(AuthErrorInfoEnum.AUTH_ACCOUNT_REGISTER_NO_PERMISSION,null, "你无权给该用户添加名称为:'" + role.getRoleName() + "'的角色");
                }
            }
        }
        for (AuthRole role : oldRoles.values()) {
            //如果新的角色列表不包含已存在的老角色
            if (!roleIds.contains(role.getId())) {
                //如果访问人没有该角色的数据权限
                if (!StpUtil.hasPermission(role.getDataPermissionCode())) {
                    throw new AuthorizationException(AuthErrorInfoEnum.AUTH_ACCOUNT_REGISTER_NO_PERMISSION,null, "你无权删除该用户名称为:'" + role.getRoleName() + "'的角色");
                } else {
                    updateNum++;
                }
            }
        }
        List<AuthUserMapRole> userMapRoles = new LinkedList<>();
        for (Long roleId : saveRoleIds) {
            AuthUserMapRole userMapRole = new AuthUserMapRole();
            userMapRole.setRoleId(roleId);
            userMapRole.setUserId(userId);
            userMapRoles.add(userMapRole);
        }
        this.removeUserRole(userId);
        this.saveBatch(userMapRoles);
        return updateNum;
    }

    private void removeUserRole(Long userId){
        if(Objects.nonNull(userId)){
            remove(new LambdaQueryWrapper<AuthUserMapRole>().eq(AuthUserMapRole::getUserId,userId));
        }
    }

    private List<AuthUserMapRole> getByUserId(Long userId){
        return list(new LambdaQueryWrapper<AuthUserMapRole>().eq(AuthUserMapRole::getUserId,userId));
    }
}
